﻿using KingerRobot.MexicoSailunMDC.SpiService;
using System.ServiceModel.Channels;
using System.Threading.Tasks;

namespace KingerRobot.MexicoSailunMDC.Biz;
/// <summary>
/// 出库线体任务创建下传
/// 出库放胎位
/// </summary>
public class WarehousingLineBiz : K8.MDCBB.Biz
{
    #region 配置参数
    private ParamData Param { get; set; }

    class ParamData
    {

        /// <summary>
        /// 设备ID
        /// </summary>
        public long EquipId { get; set; }

        /// <summary>
        /// 设备名称
        /// </summary>
        public string EquipName { get; set; }
        /// <summary>
        /// 出库放胎位A
        /// </summary>
        public long OutLocA { get; set; }
        /// <summary>
        /// 出库放胎位
        /// </summary>
        public long OutLocB { get; set; }
    }
    #endregion

    #region PLC 通讯参数
    private ValueData Data { get; set; }
    class ValueData
    {

        /// <summary>
        /// 有胎标识
        /// </summary>
        public int rStatus_A { get; set; }

        /// <summary>
        /// 有胎标识
        /// </summary>
        public int rStatus_B { get; set; }

    }
    #endregion

    #region 缓存
    private CacheData Cache { get; set; }
    class CacheData
    {
        /// <summary>
        /// A叉任务号
        /// </summary>
        public int TaskA_No { get; set; }
        /// <summary>
        /// B叉任务号
        /// </summary>
        public int TaskB_No { get; set; }
    }
    #endregion

    #region 实时日志
    private StepData Step { get; set; }
    class StepData
    {
        private string _msg = string.Empty;
        public string StepMsg
        {
            get
            {
                return this._msg;
            }
            set
            {
                if (string.IsNullOrWhiteSpace(value))
                {
                    this._msg = string.Empty;
                    return;
                }
                this._msg = $"{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}>>{value}";
            }
        }
    }
    private void StepMsg(string msg)
    {
        this.Step.StepMsg = msg;
        this.WriteLog(msg);
    }
    #endregion

    #region 文件日志（运行需要 Nlog 配置）
    private void WriteLog(string message)
    {
        K8.LSF.Client.Log(new K8.LSF.Log { Data = message });
    }
    #endregion

    /// <summary>
    /// 和 PLC 通讯对象
    /// </summary>
    private BizData BizData { get; set; }
    public int Execute(BizData writer)
    {

        // Excute 方法外使用 BizData
        this.BizData = writer;

        // 返回参数
        var result = 0;

        var taskService = K8.RSF.Client.Create<ITaskService>();

        //var taskService = new TaskImpl();

        // 任务完成
        TaskABFinishV2(taskService);
        return result;
    }

    /// <summary>
    /// 任务完成
    /// </summary>
    /// <param name="taskService"></param>
    /// <param name="inputService"></param>
    /// <param name="outputService"></param>
    private void TaskABFinishV2(ITaskService taskService)
    {

        StringBuilder stringBuilder = new();

        StringBuilder stringBuilder1 = new();
        //var taskA = Task.Run(() =>
        //{
        //    var taskStatusA = taskService.GetTaskTypeByLocId(Param.OutLocA);
        //    return taskStatusA;
        //});
        //var taskB = Task.Run(() =>
        //{
        //    var taskStatusB = taskService.GetTaskTypeByLocId(Param.OutLocB);
        //    return taskStatusB;
        //});
        //var taskStatusA = taskA.Result;
        //var taskStatusB = taskB.Result;

        var task = Task.Run(() =>
        {
            // A号完成

            var dataA = TaskAFinishV2(taskService, stringBuilder);

            return dataA;
        });

        var task1 = Task.Run(() =>
        {

            // B号完成
            var dataB = TaskBFinishV2(taskService, stringBuilder1);

            return dataB;
        });

        var dataA = task.Result;
        var dataB = task1.Result;

        this.StepMsg($"进入a放货位aaa{dataA.ToJson()}");
        this.StepMsg($"进入b放货位aaa{dataB.ToJson()}");
        // 出库任务
        //this.StepMsg($"出库完成参数：{dataA.OutN}，{dataB.OutN}，{dataA.OutTaskNo}，{dataA.OutTaskLoc}，{dataB.OutTaskNo}，{dataB.OutTaskLoc}");
        OutWriteSwitchV2(
            dataA.OutN,
            dataB.OutN,

            dataA.OutTaskNo, dataA.OutTaskLoc,
            dataB.OutTaskNo, dataB.OutTaskLoc,

            dataA.OutTask,
            dataB.OutTask);


        //var message = $"A : {stringBuilder}_B:{stringBuilder1}";
        //if (!string.IsNullOrWhiteSpace(message))
        //{
        //    this.StepMsg(message);
        //}

    }

    public IOInfo TaskAFinishV2(ITaskService taskService, StringBuilder stringBuilder)
    {
        this.StepMsg("进入a放货位");
        IOInfo iOInfo = new();
        if (Data.rStatus_A == 0)
        {
            this.StepMsg($"进入a放货位1rStatus_A{Data.rStatus_A}");
            // TODO 设置出库输送指令为 已执行
            return iOInfo;
        }
        this.StepMsg("进入a放货位111");
        // 完成信号
        (iOInfo.OutN, iOInfo.OutTask) = OutFinish_A_V2(taskService, stringBuilder);
        iOInfo.OutTaskNo = iOInfo.OutTask?.TaskNo ?? 0;
        iOInfo.OutTaskLoc = iOInfo.OutTask?.TargetLoc ?? 0;

        return iOInfo;
    }

    public IOInfo TaskBFinishV2(ITaskService taskService, StringBuilder stringBuilder)
    {
        IOInfo iOInfo = new();
        if (Data.rStatus_B == 0)
        {
            // TODO 设置出库输送指令为 已执行
            return iOInfo;
        }
        // 完成信号
        (iOInfo.OutN, iOInfo.OutTask) = OutFinish_B_V2(taskService, stringBuilder);
        iOInfo.OutTaskNo = iOInfo.OutTask?.TaskNo ?? 0;
        iOInfo.OutTaskLoc = iOInfo.OutTask?.TargetLoc ?? 0;

        return iOInfo;
    }


    /// <summary>
    /// 出库 A 完成
    /// </summary>
    /// <param name="outputService"></param>
    /// <param name="task"></param>
    /// <param name="stringBuilder"></param>
    private (int, BizTaskBean?) OutFinish_A_V2(ITaskService taskService, StringBuilder stringBuilder)
    {
        // 查询当前位置是否有胎
        var taskStatus = taskService.GetTaskTypeByLocId(Param.OutLocA);

        var result = taskStatus.Sign;
        var taskId = taskStatus.TaskId;
        BizTaskBean bizTaskBean;
        #region 线体异常出库
        if (result == 2)
        {
            bizTaskBean = OutLocLineCreateTask(Param.OutLocA, taskId);
            if (bizTaskBean is null)
            {
                stringBuilder.Append($"A货叉 线体异常口任务创建，失败{Param.OutLocA},{taskId} | ");
                return (0, null);
            }
            stringBuilder.Append($"A货叉 线体异常口任务创建成功 | ");
            return (1, bizTaskBean);
        }
        #endregion


        #region 创建线体任务
        // 创建线体任务
        if (result == 1)
        {

            bizTaskBean = OutLineCreateTask(Param.OutLocA, taskId);
            if (bizTaskBean is null)
            {
                stringBuilder.Append($"A货叉 线体任务创建，失败{Param.OutLocA},{taskId} | ");
                return (0, null);
            }
            stringBuilder.Append($"A货叉 线体任务创建成功 | ");
            return (1, bizTaskBean);
        }
        #endregion

        #region 指令重下
        // 指令重下
        if (result == 4)
        {
            bizTaskBean = GetTaskBean(taskId);
            if (bizTaskBean is null)
            {
                stringBuilder.Append($"A货叉 线体任务重下，失败{Param.OutLocA},{taskId} | ");
                return (0, null);
            }
            stringBuilder.Append($"A货叉 线体任务重下成功 | ");
            return (1, bizTaskBean);
        }
        #endregion

        return (0, null);
    }


    /// <summary>
    /// 出库 B 完成
    /// </summary>
    /// <param name="taskService"></param>
    /// <param name="stringBuilder"></param>
    private (int, BizTaskBean?) OutFinish_B_V2(ITaskService taskService, StringBuilder stringBuilder)
    {
        // 查询当前位置是否有胎
        var taskStatus = taskService.GetTaskTypeByLocId(Param.OutLocB);
        var result = taskStatus.Sign;
        var taskId = taskStatus.TaskId;
        BizTaskBean bizTaskBean;
        #region 线体异常出库
        if (result == 2)
        {
            bizTaskBean = OutLocLineCreateTask(Param.OutLocB, taskId);
            if (bizTaskBean is null)
            {
                stringBuilder.Append($"B货叉 线体异常口任务创建，失败{Param.OutLocB},{taskId} | ");
                return (0, null);
            }
            stringBuilder.Append($"B货叉 线体异常口任务创建成功 | ");
            return (1, bizTaskBean);
        }
        #endregion


        #region 创建线体任务
        // 创建线体任务
        if (result == 1)
        {
            this.StepMsg($"出库B完成292,{taskId}");
            bizTaskBean = OutLineCreateTask(Param.OutLocB, taskId);
            this.StepMsg($"出库B完成294,{taskId}");
            if (bizTaskBean is null)
            {
                stringBuilder.Append($"B货叉 线体任务创建，失败{Param.OutLocB},{taskId} | ");
                return (0, null);
            }
            stringBuilder.Append($"B货叉 线体任务创建成功 | ");
            return (1, bizTaskBean);
        }
        #endregion

        #region 指令重下
        // 指令重下
        if (result == 4)
        {
            bizTaskBean = GetTaskBean(taskId);
            if (bizTaskBean is null)
            {
                stringBuilder.Append($"B货叉 线体任务重下，失败{Param.OutLocB},{taskId} | ");
                return (0, null);
            }
            stringBuilder.Append($"B货叉 线体任务重下成功 | ");
            return (1, bizTaskBean);
        }
        #endregion

        return (0, null);

    }
    //14.833
    //21:21:15.443


    /// <summary>
    /// 出库线体任务创建
    /// </summary>
    private BizTaskBean OutLineCreateTask(long locId, long taskId)
    {
        // 创建任务
        var service = K8.RSF.Client.Create<IExWarehousingAfterService>();
        //var resultId = service.CreateTask(locId, taskId);


        // 获取任务信息
        //var task = GetTaskBean(resultId);
        var task = service.CreateTaskV2(locId, taskId);
        if (task is null)
        {
            return null;
        }

        return task;
    }

    /// <summary>
    /// 出库线体任务创建
    /// </summary>
    private BizTaskBean OutLocLineCreateTask(long locId, long taskId)
    {
        // 创建任务
        var service = K8.RSF.Client.Create<IExWarehousingAfterService>();
        var resultId = service.CreateLocOutTask(locId, taskId);

        if (resultId <= 0)
        {
            return null;
        }

        // 获取任务信息
        var task = GetTaskBean(resultId);
        if (task is null)
        {
            return null;
        }

        return task;
    }
    private BizTaskBean GetTaskBean(long resultId)
    {
        var taskService = K8.RSF.Client.Create<ITaskService>();
        var task = taskService.GetTaskByTaskId(resultId);

        return task;
    }

    private int SetOutATaskFlagV2(int outTaskNoA, long outTaskLocA, BizTaskBean outATask)
    {
        var service = K8.RSF.Client.Create<IExWarehousingAfterService>();
        //service.CreateOrUpdateWcsOutputLog(outTaskNoA, 7, "单叉");
        if (Data.rStatus_A == 0)
        {
            this.StepMsg($"单胎 A 放胎位无胎");
            return 0;
        }
        if (outATask is null)
        {
            return 0;
        }
        var productCodeA = outATask.ProductCode;
        if (string.IsNullOrWhiteSpace(productCodeA))
        {
            return 0;
        }
        this.StepMsg($" A叉下发记录 条码{productCodeA}，任务{outATask.TaskNo}，目的地{outATask.TargetCmdPlcLoc}");
        object writeData = new
        {
            Destination_A = outATask.TargetCmdPlcLoc,       // 目标地址
            WorkNo_A = outATask.TaskNo,                     // 流水号
                                                            //ProductCode_A = productCodeA,
            GroupId_A = outATask.TaskGroup,
            //Size_A = outATask.OutSize,
        };
        var mark = this.BizData.WriteData(writeData);
        if (mark > 0)
        {
            service.CreateOrUpdateWcsOutputLog(outTaskNoA, 8);
            mark = service.ExecuteTask(outTaskNoA, outTaskLocA);
            if (mark == 0)
            {
                this.StepMsg($"A货叉任务不存在{outTaskNoA}，{outTaskLocA}");
                return 0;
            }
            //mark = this.BizData.WriteData(new
            //{
            //    TaskFlag_A = 1,
            //});
            //if (mark <= 0)
            //{
            //没写入成功，再次执行
            //service.UpdateCmdStatusByTaskId(outATask.Id, (int)EnumTaskCmdStatus.Executable, (int)EnumTaskType.Transportation);
            //}
        }
        return 1;
    }
    private int SetOutBTaskFlagV2(int outTaskNoB, long outTaskLocB, BizTaskBean outBTask)
    {
        var service = K8.RSF.Client.Create<IExWarehousingAfterService>();
        service.CreateOrUpdateWcsOutputLog(outTaskNoB, 7, "单叉");
        if (Data.rStatus_B == 0)
        {
            this.StepMsg($"单胎 B 放胎位无胎");
            return 0;
        }
        if (outBTask is null)
        {
            return 0;
        }
        var productCodeB = outBTask.ProductCode;
        if (string.IsNullOrWhiteSpace(productCodeB))
        {
            return 0;
        }
        var codeB = productCodeB.Chunk(2).ToList();
        this.StepMsg($" B叉下发记录 条码{productCodeB}，任务{outBTask.TaskNo}，目的地{outBTask.TargetCmdPlcLoc},TaskGroup{outBTask.TaskGroup}");
        object writeData = new
        {
            Destination_B = outBTask.TargetCmdPlcLoc,       // 目标地址
            WorkNo_B = outBTask.TaskNo,                     // 流水号
            //ProductCode_B = productCodeB,
            GroupId_B = outBTask.TaskGroup,
            //Size_B = outBTask.OutSize,

        };
        var mark = this.BizData.WriteData(writeData);
        if (true)//mark > 0)
        {
            service.CreateOrUpdateWcsOutputLog(outTaskNoB, 8);
            mark = service.ExecuteTask(outTaskNoB, outTaskLocB);
            if (mark == 0)
            {
                this.StepMsg($"B货叉任务不存在{outTaskNoB}，{outTaskLocB}");
                return 0;
            }
            //mark = this.BizData.WriteData(new
            //{
            //    TaskFlag_B = 1,
            //});
            //if (mark <= 0)
            //{
            //    //没写入成功，再次执行
            //    service.UpdateCmdStatusByTaskId(outBTask.Id, (int)EnumTaskCmdStatus.Executable, (int)EnumTaskType.Transportation);
            //}
        }
        return 1;
    }
    private int SetOutABTaskFlagV2(int outTaskNoA, long outTaskLocA, int outTaskNoB, long outTaskLocB, BizTaskBean outATask, BizTaskBean outBTask)
    {
        var service = K8.RSF.Client.Create<IExWarehousingAfterService>();
        //service.CreateOrUpdateWcsOutputLog(outTaskNoA, 7, "双叉");
        //service.CreateOrUpdateWcsOutputLog(outTaskNoB, 7, "双叉");
        if (Data.rStatus_A == 0 || Data.rStatus_B == 0)
        {
            this.StepMsg($"双胎 A：{Data.rStatus_A},B：{Data.rStatus_B} 放胎位无胎");
            return 0;
        }
        if (outATask is null || outBTask is null)
        {
            return 0;
        }
        var productCodeA = outATask.ProductCode;
        if (string.IsNullOrWhiteSpace(productCodeA))
        {
            return 0;
        }
        var codeA = productCodeA.Chunk(2).ToList();

        var productCodeB = outBTask.ProductCode;
        if (string.IsNullOrWhiteSpace(productCodeB))
        {
            return 0;
        }
        var codeB = productCodeB.Chunk(2).ToList();


        var mark = 0;
        try
        {
            mark = service.ExecuteTask(outTaskNoA, outTaskLocA);
        }
        catch (Exception ex)
        {
            this.StepMsg($"任务{outTaskNoA}，修改状态失败:{ex.ToString()}");
        }
        try
        {
            mark += service.ExecuteTask(outTaskNoB, outTaskLocB);
        }
        catch (Exception ex)
        {
            this.StepMsg($"任务{outTaskNoB}，修改状态失败:{ex.ToString()}");
        }
        if (mark == 0)
        {
            this.StepMsg($"双货叉任务不存在{outTaskNoA}，{outTaskLocA}，{outTaskNoB}，{outTaskLocB}");
            return 0;
        }
        if (mark > 0)
        {

            this.StepMsg($" A叉下发记录 组号{outATask.TaskGroup}，任务{outATask.TaskNo}，目的地{outATask.TargetCmdPlcLoc} B叉下发记录 组号{outBTask.TaskGroup}，任务{outBTask.TaskNo}，目的地{outBTask.TargetCmdPlcLoc}");
            object writeData = new
            {
                Destination_A = outATask.TargetCmdPlcLoc,       // 目标地址
                WorkNo_A = outATask.TaskNo,                     // 流水号
                                                                //ProductCode_A = productCodeA,
                                                                //Size_A = outATask.OutSize,
                GroupId_A = outATask.TaskGroup,

                Destination_B = outBTask.TargetCmdPlcLoc,       // 目标地址
                WorkNo_B = outBTask.TaskNo,
                GroupId_B = outBTask.TaskGroup,
                // 流水号
                //ProductCode_B = productCodeB,
                //Size_B = outBTask.OutSize,
            };
            mark = this.BizData.WriteData(writeData);
            this.StepMsg($"任务a{outTaskNoA}，任务b{outTaskNoB},成功下发");
        }
        else
        {
            //没写入成功，再次执行
            service.UpdateCmdStatusByTaskId(outATask.Id, (int)EnumTaskCmdStatus.Executable, (int)EnumTaskType.Transportation);
            service.UpdateCmdStatusByTaskId(outBTask.Id, (int)EnumTaskCmdStatus.Executable, (int)EnumTaskType.Transportation);
        }



    


        //this.StepMsg($" A叉下发记录 组号{outATask.TaskGroup}，任务{outATask.TaskNo}，目的地{outATask.TargetCmdPlcLoc} B叉下发记录 组号{outBTask.TaskGroup}，任务{outBTask.TaskNo}，目的地{outBTask.TargetCmdPlcLoc}");
        //object writeData = new
        //{
        //    Destination_A = outATask.TargetCmdPlcLoc,       // 目标地址
        //    WorkNo_A = outATask.TaskNo,                     // 流水号
        //    //ProductCode_A = productCodeA,
        //    //Size_A = outATask.OutSize,
        //    GroupId_A = outATask.TaskGroup,

        //    Destination_B = outBTask.TargetCmdPlcLoc,       // 目标地址
        //    WorkNo_B = outBTask.TaskNo,
        //    GroupId_B = outBTask.TaskGroup,
        //    // 流水号
        //    //ProductCode_B = productCodeB,
        //    //Size_B = outBTask.OutSize,
        //};
        //var mark = this.BizData.WriteData(writeData);

        //if (mark > 0)
        //{
        //    this.StepMsg($"任务a{outTaskNoA}，任务b{outTaskNoB},成功下发");
        //    //service.CreateOrUpdateWcsOutputLog(outTaskNoA, 8);
        //    //service.CreateOrUpdateWcsOutputLog(outTaskNoB, 8);
        //    service = K8.RSF.Client.Create<IExWarehousingAfterService>();
        //    try
        //    {
        //        mark = service.ExecuteTask(outTaskNoA, outTaskLocA);
        //    }
        //    catch (Exception ex)
        //    {
        //        this.StepMsg($"任务{outTaskNoA}，修改状态失败:{ex.ToString()}");
        //    }
        //    try
        //    {
        //        mark += service.ExecuteTask(outTaskNoB, outTaskLocB);
        //    }
        //    catch (Exception ex)
        //    {
        //        this.StepMsg($"任务{outTaskNoB}，修改状态失败:{ex.ToString()}");
        //    }

        //    if (mark == 0)
        //    {
        //        this.StepMsg($"双货叉任务不存在{outTaskNoA}，{outTaskLocA}，{outTaskNoB}，{outTaskLocB}");
        //        return 0;
        //    }
        //    //mark = this.BizData.WriteData(new
        //    //{
        //    //    TaskFlag_A = 1,
        //    //    TaskFlag_B = 1,
        //    //});
        //    //this.StepMsg($" A叉B叉标志位完成");
        //    //if (mark <= 0)
        //    //{
        //    //    //没写入成功，再次执行
        //    //    service.UpdateCmdStatusByTaskId(outATask.Id, (int)EnumTaskCmdStatus.Executable, (int)EnumTaskType.Transportation);
        //    //    service.UpdateCmdStatusByTaskId(outBTask.Id, (int)EnumTaskCmdStatus.Executable, (int)EnumTaskType.Transportation);
        //    //}
        //}
        return 1;
    }
private int OutWriteSwitchV2(int outA, int outB, int outTaskNoA, long outTaskLocA, int outTaskNoB, long outTaskLocB, BizTaskBean outATask, BizTaskBean outBTask) => (outA, outB) switch
{
    (1, 1) => SetOutABTaskFlagV2(outTaskNoA, outTaskLocA, outTaskNoB, outTaskLocB, outATask, outBTask),
    (1, 0) => SetOutATaskFlagV2(outTaskNoA, outTaskLocA, outATask),
    (0, 1) => SetOutBTaskFlagV2(outTaskNoB, outTaskLocB, outBTask),
    _ => 0,
};
/// <summary>
/// 获取拆分条码
/// </summary>
/// <param name="codes"></param>
/// <param name="ind">从1开始</param>
/// <returns></returns>
private string GetProductItem(List<char[]> codes, int ind)
{
    if (codes.Count >= ind)
    {
        return new string(codes[ind - 1]);
    }
    return string.Empty;
}

public class IOInfo
{
    public long InTargetLoc { get; set; }
    public int InN { get; set; }
    public int OutTaskNo { get; set; }
    public long OutTaskLoc { get; set; }
    public BizTaskBean OutTask { get; set; }
    public int OutN { get; set; }
}
}
